package com.funsport.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.funsport.common.enums.EventStatus;
import com.funsport.entity.Event;
import com.funsport.entity.EventSignup;
import com.funsport.exception.BusinessException;
import com.funsport.mapper.EventSignupMapper;
import com.funsport.service.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;

/**
 * EventSignup Service实现
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class EventSignupServiceImpl extends ServiceImpl<EventSignupMapper, EventSignup> implements IEventSignupService {

    private final IEventService eventService;
    private final IPointsService pointsService;
    private final INotificationService notificationService;
    private final IClubMemberService clubMemberService;

    @Override
    @Transactional
    public boolean signupEvent(Long userId, Long eventId, String note) {
        Event event = eventService.getById(eventId);
        if (event == null) {
            throw new BusinessException("活动不存在");
        }

        // 检查活动状态
        if (event.getStatus() != EventStatus.PUBLISHED) {
            throw new BusinessException("活动未发布，无法报名");
        }

        // 检查报名截止时间
        if (event.getRegistrationDeadline() != null && 
            LocalDateTime.now().isAfter(event.getRegistrationDeadline())) {
            throw new BusinessException("报名已截止");
        }

        // 检查活动是否已开始
        if (LocalDateTime.now().isAfter(event.getStartTime())) {
            throw new BusinessException("活动已开始，无法报名");
        }

        // 检查是否已报名
        EventSignup existing = getOne(new LambdaQueryWrapper<EventSignup>()
                .eq(EventSignup::getUserId, userId)
                .eq(EventSignup::getEventId, eventId));

        if (existing != null && !"cancelled".equals(existing.getStatus())) {
            throw new BusinessException("您已报名该活动");
        }

        // 检查是否已满（候补名单）
        boolean isWaitlist = event.getCurrentParticipants() >= event.getMaxParticipants();

        // 检查是否需要审核
        String status;
        if (Boolean.TRUE.equals(event.getNeedApproval())) {
            status = "pending";
        } else if (isWaitlist) {
            status = "confirmed";  // 候补也是已确认状态，只是isWaitlist=true
        } else {
            status = "confirmed";
        }

        EventSignup signup;
        if (existing != null) {
            // 更新现有记录
            existing.setStatus(status);
            existing.setIsWaitlist(isWaitlist);
            existing.setSignupNote(note);
            updateById(existing);
            signup = existing;
        } else {
            // 创建新记录
            signup = new EventSignup();
            signup.setEventId(eventId);
            signup.setUserId(userId);
            signup.setStatus(status);
            signup.setIsWaitlist(isWaitlist);
            signup.setSignupNote(note);
            signup.setCheckedIn(false);
            save(signup);
        }

        // 如果不是候补且不需要审核，增加参与人数
        if (!isWaitlist && "confirmed".equals(status)) {
            event.setCurrentParticipants(event.getCurrentParticipants() + 1);
            eventService.updateById(event);

            // 奖励用户积分
            pointsService.awardEventPoints(userId, eventId, "signup");

            // 如果有俱乐部，增加成员活动参与数
            if (event.getClubId() != null) {
                clubMemberService.addContributionPoints(userId, event.getClubId(), 10);
            }
        }

        // 发送报名确认通知
        notificationService.sendSignupConfirmation(userId, event.getTitle(), event.getStartTime());

        String logMessage = isWaitlist ? "用户进入候补名单" : "用户成功报名活动";
        log.info("{}: userId={}, eventId={}", logMessage, userId, eventId);

        return true;
    }

    @Override
    @Transactional
    public boolean cancelSignup(Long userId, Long eventId) {
        EventSignup signup = getOne(new LambdaQueryWrapper<EventSignup>()
                .eq(EventSignup::getUserId, userId)
                .eq(EventSignup::getEventId, eventId)
                .in(EventSignup::getStatus, "pending", "confirmed"));

        if (signup == null) {
            throw new BusinessException("未找到报名记录");
        }

        Event event = eventService.getById(eventId);
        
        // 检查是否允许取消（活动开始前2小时）
        if (LocalDateTime.now().isAfter(event.getStartTime().minusHours(2))) {
            throw new BusinessException("活动即将开始，无法取消报名");
        }

        // 更新状态为已取消
        signup.setStatus("cancelled");
        updateById(signup);

        // 如果不是候补，减少参与人数
        if (!Boolean.TRUE.equals(signup.getIsWaitlist()) && "confirmed".equals(signup.getStatus())) {
            event.setCurrentParticipants(event.getCurrentParticipants() - 1);
            eventService.updateById(event);

            // 尝试从候补名单转正一个
            promoteFromWaitlist(eventId);
        }

        // 创建通知
        notificationService.createInAppNotification(
                userId,
                "取消报名成功",
                String.format("您已成功取消活动【%s】的报名", event.getTitle()),
                "signup_cancelled",
                eventId,
                "event"
        );

        log.info("用户取消报名: userId={}, eventId={}", userId, eventId);
        return true;
    }

    @Override
    @Transactional
    public boolean checkIn(Long userId, Long eventId) {
        EventSignup signup = getOne(new LambdaQueryWrapper<EventSignup>()
                .eq(EventSignup::getUserId, userId)
                .eq(EventSignup::getEventId, eventId)
                .eq(EventSignup::getStatus, "confirmed"));

        if (signup == null) {
            throw new BusinessException("未找到确认的报名记录");
        }

        if (Boolean.TRUE.equals(signup.getCheckedIn())) {
            throw new BusinessException("已经签到过了");
        }

        Event event = eventService.getById(eventId);

        // 检查签到时间（活动开始前30分钟至活动结束）
        LocalDateTime now = LocalDateTime.now();
        if (now.isBefore(event.getStartTime().minusMinutes(30))) {
            throw new BusinessException("签到时间未到");
        }
        if (now.isAfter(event.getEndTime())) {
            throw new BusinessException("活动已结束，无法签到");
        }

        // 签到
        signup.setCheckedIn(true);
        signup.setCheckInTime(LocalDateTime.now());
        signup.setStatus("attended");
        updateById(signup);

        // 奖励签到积分
        pointsService.awardEventPoints(userId, eventId, "attend");

        // 如果有俱乐部，增加成员贡献积分
        if (event.getClubId() != null) {
            clubMemberService.addContributionPoints(userId, event.getClubId(), 20);
        }

        log.info("用户签到成功: userId={}, eventId={}", userId, eventId);
        return true;
    }

    @Override
    @Transactional
    public boolean approveSignup(Long signupId, Boolean approved, Long operatorId) {
        EventSignup signup = getById(signupId);
        if (signup == null || !"pending".equals(signup.getStatus())) {
            throw new BusinessException("无效的报名记录");
        }

        Event event = eventService.getById(signup.getEventId());

        // 检查操作者权限（活动创建者或俱乐部管理员）
        boolean hasPermission = event.getCreatorId().equals(operatorId);
        if (event.getClubId() != null && !hasPermission) {
            hasPermission = clubMemberService.isAdmin(operatorId, event.getClubId());
        }

        if (!hasPermission) {
            throw new BusinessException("您没有权限审核报名");
        }

        if (Boolean.TRUE.equals(approved)) {
            // 检查是否已满
            if (event.getCurrentParticipants() >= event.getMaxParticipants()) {
                // 进入候补名单
                signup.setStatus("confirmed");
                signup.setIsWaitlist(true);
            } else {
                // 通过申请
                signup.setStatus("confirmed");
                signup.setIsWaitlist(false);
                
                // 增加参与人数
                event.setCurrentParticipants(event.getCurrentParticipants() + 1);
                eventService.updateById(event);

                // 奖励积分
                pointsService.awardEventPoints(signup.getUserId(), signup.getEventId(), "signup");
            }

            updateById(signup);

            // 发送通知
            notificationService.createInAppNotification(
                    signup.getUserId(),
                    "活动报名申请已通过",
                    String.format("恭喜您，活动【%s】的报名申请已通过！", event.getTitle()),
                    "signup_approved",
                    event.getId(),
                    "event"
            );

            log.info("活动报名申请已通过: signupId={}, operatorId={}", signupId, operatorId);
        } else {
            // 拒绝申请
            signup.setStatus("cancelled");
            updateById(signup);

            // 发送通知
            notificationService.createInAppNotification(
                    signup.getUserId(),
                    "活动报名申请未通过",
                    String.format("很抱歉，活动【%s】的报名申请未通过。", event.getTitle()),
                    "signup_rejected",
                    event.getId(),
                    "event"
            );

            log.info("活动报名申请已拒绝: signupId={}, operatorId={}", signupId, operatorId);
        }

        return true;
    }

    @Override
    @Transactional
    public int promoteFromWaitlist(Long eventId) {
        Event event = eventService.getById(eventId);
        if (event == null) {
            return 0;
        }

        // 计算可转正人数
        int availableSlots = event.getMaxParticipants() - event.getCurrentParticipants();
        if (availableSlots <= 0) {
            return 0;
        }

        // 获取候补名单（按报名时间排序）
        List<EventSignup> waitlist = list(new LambdaQueryWrapper<EventSignup>()
                .eq(EventSignup::getEventId, eventId)
                .eq(EventSignup::getStatus, "confirmed")
                .eq(EventSignup::getIsWaitlist, true)
                .orderByAsc(EventSignup::getCreatedAt)
                .last("LIMIT " + availableSlots));

        int promotedCount = 0;
        for (EventSignup signup : waitlist) {
            signup.setIsWaitlist(false);
            updateById(signup);

            // 增加参与人数
            event.setCurrentParticipants(event.getCurrentParticipants() + 1);

            // 奖励积分
            pointsService.awardEventPoints(signup.getUserId(), eventId, "signup");

            // 发送通知
            notificationService.createInAppNotification(
                    signup.getUserId(),
                    "候补转正通知",
                    String.format("恭喜您，活动【%s】有空位了，您已从候补名单转为正式参与者！", event.getTitle()),
                    "waitlist_promoted",
                    eventId,
                    "event"
            );

            promotedCount++;
        }

        if (promotedCount > 0) {
            eventService.updateById(event);
            log.info("候补名单转正: eventId={}, 转正人数={}", eventId, promotedCount);
        }

        return promotedCount;
    }

    @Override
    @Transactional
    public boolean rateEvent(Long userId, Long eventId, Integer rating, String review) {
        EventSignup signup = getOne(new LambdaQueryWrapper<EventSignup>()
                .eq(EventSignup::getUserId, userId)
                .eq(EventSignup::getEventId, eventId)
                .eq(EventSignup::getStatus, "attended"));

        if (signup == null) {
            throw new BusinessException("您未参加该活动，无法评价");
        }

        if (rating < 1 || rating > 5) {
            throw new BusinessException("评分必须在1-5之间");
        }

        // 更新评价
        signup.setRating(rating);
        signup.setReview(review);
        updateById(signup);

        // 奖励积分
        pointsService.addUserPoints(userId, 5, "活动评价", "event", eventId);

        log.info("用户评价活动: userId={}, eventId={}, rating={}", userId, eventId, rating);
        return true;
    }

    @Override
    public List<EventSignup> getEventParticipants(Long eventId, String status) {
        LambdaQueryWrapper<EventSignup> query = new LambdaQueryWrapper<EventSignup>()
                .eq(EventSignup::getEventId, eventId)
                .orderByDesc(EventSignup::getCreatedAt);

        if (status != null && !status.isEmpty()) {
            query.eq(EventSignup::getStatus, status);
        }

        return list(query);
    }

    @Override
    public List<EventSignup> getUserSignups(Long userId, String status) {
        LambdaQueryWrapper<EventSignup> query = new LambdaQueryWrapper<EventSignup>()
                .eq(EventSignup::getUserId, userId)
                .orderByDesc(EventSignup::getCreatedAt);

        if (status != null && !status.isEmpty()) {
            query.eq(EventSignup::getStatus, status);
        }

        return list(query);
    }

    @Override
    public boolean hasSignedUp(Long userId, Long eventId) {
        EventSignup signup = getOne(new LambdaQueryWrapper<EventSignup>()
                .eq(EventSignup::getUserId, userId)
                .eq(EventSignup::getEventId, eventId)
                .in(EventSignup::getStatus, "pending", "confirmed", "attended"));

        return signup != null;
    }

    @Override
    public int getConfirmedCount(Long eventId) {
        return (int) count(new LambdaQueryWrapper<EventSignup>()
                .eq(EventSignup::getEventId, eventId)
                .eq(EventSignup::getStatus, "confirmed")
                .eq(EventSignup::getIsWaitlist, false));
    }
}
